package com.codeoss.framework.service.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.codeoss.framework.context.UserContext;
import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.data.metadata.Order;
import com.codeoss.framework.data.metadata.Query;
import com.codeoss.framework.data.metadata.Table;
import com.codeoss.framework.data.store.ITableStore;
import com.codeoss.framework.db.util.OracleDataConvertUtil;
import com.codeoss.framework.db.util.ValueNamePairUtil;
import com.codeoss.framework.response.MainResponse;
import com.codeoss.framework.service.IMainService;
import com.codeoss.framework.util.IOUtil;
import com.codeoss.framework.util.LoginLogUtil;
import com.codeoss.framework.util.StringUtils;
import com.codeoss.framework.util.ValueNamePair;
import com.codeoss.framework.view.model.HierarchyData;
import com.codeoss.framework.view.util.DataSourceUtil;
import com.codeoss.module.ir.model.IrApplication;
import com.codeoss.module.ir.model.IrMenu;
import com.codeoss.module.ir.service.IIrMenuService;
import com.codeoss.module.ir.service.impl.IrApplicationService;
import com.codeoss.module.res.model.ResUser;
import com.codeoss.module.res.service.IResUserService;

@Service
public class MainService implements IMainService {
	@Autowired
	private IIrMenuService irMenuService;
	@Autowired
	private IResUserService resUserService;
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Autowired
	private DataSourceUtil dataSourceUtil;
	@Value("${framework.db-type}")
	private String dbType;
	@Autowired
	private ValueNamePairUtil valueNamePairUtil;
	@Autowired
	private ITableStore tableStore;
	@Autowired
	private IrApplicationService irApplicationService;
	@Autowired
	private LoginLogUtil loginLogUtil;
	@Override
	public MainResponse init() {
		// TODO Auto-generated method stub
		MainResponse mainResponse=new MainResponse();
		YunContext yunContext=YunContext.getCurrentContext();
		
		Table table=tableStore.get("ir_application");
		Query query=new Query();
		query.addOrder(Order.asc("id"));
		List<ValueNamePair> applicationList=valueNamePairUtil.getValueNamePairList(yunContext, table, query, true, false);
		mainResponse.setApplicationList(applicationList);
		mainResponse.setApplicationName(applicationList.get(0).getName());
		
		List<Map<String,Object>> mapList=irMenuService.getCanAccessMenuList((Long)applicationList.get(0).getValue());
		if(dbType.equals("oracle")) {
			mapList=OracleDataConvertUtil.doConvert(mapList);
		}
		HierarchyData menu=dataSourceUtil.convertTableDataToHierarchyData(yunContext, mapList);
		mainResponse.setMenu(menu);
		fillMenu(menu);
		if(menu.getChildren().size()==0) {
			mapList=irMenuService.getCanAccessMenuList((Long)applicationList.get(1).getValue());
			if(dbType.equals("oracle")) {
				mapList=OracleDataConvertUtil.doConvert(mapList);
			}
			menu=dataSourceUtil.convertTableDataToHierarchyData(yunContext, mapList);
			mainResponse.setMenu(menu);
			fillMenu(menu);
			mainResponse.setApplicationName(applicationList.get(1).getName());
		}
		UserContext userContext=UserContext.getCurrentUserContext();
		mainResponse.setUsername(userContext.getUsername());
		ResUser resUser=resUserService.getById(userContext.getResUserId());
		mainResponse.setDashboardPage(resUser.getDashboardPage());
		
		return mainResponse;
	}
	
	private void  fillMenu(HierarchyData menu) {
		List<HierarchyData> list=new ArrayList<HierarchyData>();
		list.add(menu);
		
		for(int i=menu.getChildren().size()-1;i>=0;i--) {
			HierarchyData moduleData=menu.getChildren().get(i);
			if(moduleData.getChildren()==null ||moduleData.getChildren().size()==0) {
				menu.getChildren().remove(i);
				continue;
			}
			for(int j=moduleData.getChildren().size()-1;j>=0;j--) {
				HierarchyData categoryData=moduleData.getChildren().get(j);
				if(categoryData.getChildren()==null ||categoryData.getChildren().size()==0) {
					moduleData.getChildren().remove(j);
					continue;
				}
			}
		}
		
		for(int i=menu.getChildren().size()-1;i>=0;i--) {
			HierarchyData moduleData=menu.getChildren().get(i);
			if(moduleData.getChildren()==null ||moduleData.getChildren().size()==0) {
				menu.getChildren().remove(i);
				continue;
			}
		}
	}
	
	@Override
	public MainResponse getPageCodeByMenuId(Long menuId) {
		// TODO Auto-generated method stub
		MainResponse mainResponse=new MainResponse();
		IrMenu irMenu=irMenuService.getById(menuId);
		mainResponse.setPageCode(irMenu.getPageCode());
		mainResponse.setMenuType(irMenu.getMenuType());
		return mainResponse;
	}
	
	@Override
	public MainResponse getAvatar() {
		// TODO Auto-generated method stub
		MainResponse mainResponse=new MainResponse();
		UserContext userContext=UserContext.getCurrentUserContext();
		ResUser resUser=resUserService.getById(userContext.getResUserId());
		mainResponse.setAvatar((byte[])resUser.getImage());
		return mainResponse;
	}
	@Override
	@Transactional
	public MainResponse changePassword(String oldPassword, String newPassword, String newPassword2) {
		// TODO Auto-generated method stub
		MainResponse mainResponse=new MainResponse();
		UserContext userContext=UserContext.getCurrentUserContext();
		ResUser resUser=resUserService.getById(userContext.getResUserId());
		if(!passwordEncoder.matches(oldPassword, resUser.getPassword())) {
			throw new RuntimeException("密码不正确");
		}
		if(StringUtils.isEmpty(newPassword)) {
			throw new RuntimeException("密码不能为空");
		}
		if(!newPassword.equals(newPassword2)) {
			throw new RuntimeException("2次密码输入不一致");
		}
		String encodePassword=passwordEncoder.encode(newPassword);
		resUser.setPassword(encodePassword);
		resUserService.update(resUser);
		return mainResponse;
	}

	@Override
	public MainResponse getMenuIconContent(Long menuId) {
		// TODO Auto-generated method stub
		MainResponse mainResponse=new MainResponse();
		IrMenu irMenu=irMenuService.getById(menuId);
		String icon=irMenu.getIcon();
		if(!StringUtils.isEmpty(icon)) {
			if(icon.startsWith("classpath:")) {
				icon=icon.substring("classpath:".length());
				InputStream is = this.getClass().getClassLoader().getResourceAsStream(icon);
				ByteArrayOutputStream os=new ByteArrayOutputStream();
				byte b[]=new byte[1024];
				int len=0;
				try {
					while((len=is.read(b))!=-1) {
						os.write(b, 0, len);
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					throw new RuntimeException(e);
				}finally {
					IOUtil.closeInputStream(is);
				}
				mainResponse.setMenuIconContent(os.toByteArray());
			}
		}
		return mainResponse;
	}

	@Override
	public MainResponse onApplicationChangeHandler(Long applicationId) {
		// TODO Auto-generated method stub
		MainResponse mainResponse=new MainResponse();
		YunContext yunContext=YunContext.getCurrentContext();
		List<Map<String,Object>> mapList=irMenuService.getCanAccessMenuList(applicationId);
		if(dbType.equals("oracle")) {
			mapList=OracleDataConvertUtil.doConvert(mapList);
		}
		HierarchyData menu=dataSourceUtil.convertTableDataToHierarchyData(yunContext, mapList);
		mainResponse.setMenu(menu);
		fillMenu(menu);
		IrApplication irApplication=irApplicationService.getById(applicationId);
		mainResponse.setApplicationName(irApplication.getName());
		return mainResponse;
	}

	@Override
	public MainResponse logout() {
		// TODO Auto-generated method stub
		MainResponse mainResponse=new MainResponse();
		loginLogUtil.logLogout();
		return mainResponse;
	}

}
